#ifndef TRANSANALYSIS_H
#define TRANSANALYSIS_H

#include "transaction.h"
#include <QVector>
#include <QString>
#include <QStringList>
#include <assert.h>

#include <iostream>
/**
 * @brief The TransPack class.
 * Pack the string and build the transaction.
 * The string format of the transaction should be:
 * HEAD;NAME:TIME;COLUMNAME:VALUE;END
 */
template<typename T>
class TransPack {
private:
    typedef void(T::*CallbackFunc)(const Transaction&);

    QString HEAD;
    QString END;
    T* Callback_obj;
    CallbackFunc Callback_func;

public:

    TransPack() :
        HEAD("HEAD")
        , END("END")
        , Callback_obj(NULL)
        , Callback_func(NULL)
    { }

    virtual ~TransPack() {
    }

    void setCallBack(T* Obj, CallbackFunc Func) {
        Callback_obj = Obj;
        Callback_func = Func;
    }

    /**
     * @brief addLine
     * @param line
     * @return true means this line is successful parsed.
     *  UDP format should be
     *  HEAD;NAME:TIME;COLUMNAME:VALUE;END
     */
    bool addLine(const char* line) {

        QString str(line);
        QStringList list = str.split(";");

        bool list_size_check = (list.size() >= 3);
        bool head_check = (list[0] == HEAD);
        bool end_check = (list[list.size()-1] == END);
        if ( !list_size_check || !head_check || !end_check ) {                        
            return false;
        }

        QString& body = list[1];
        QStringList name_time = body.split(":");
        QString& name = name_time[0];
        bool ok = false;
        int time = name_time[1].toInt(&ok);
        if (!ok) {                 
            return false;
        }
        else {
            Transaction transaction(name, time);

            if (list.size() > 3) {
                for (int i = 2; i<list.size()-1; i++) {
                    QStringList colum_value = list[i].split(":");
                    if (colum_value.size() != 2 ) {
                        return false;
                    }

                    QString& colum = colum_value[0];
                    QString& value = colum_value[1];

                    transaction.appendColum(colum, value);
                }
            }

            // Callback function to pass the transaction to upper node.
            if (Callback_obj != NULL && Callback_func != NULL)
                (Callback_obj->*Callback_func)(transaction);

            return true;
        } // End of else
    } // End of addTransaction function
};

class TransUnPack {

public:
    bool addTransaction(const Transaction& transaction) {
        // Step 1, get Name and time;
        QString name;
        QString time;

        name = transaction.getName();
        time = QString::number(transaction.getTime());
        QString line = "HEAD;"+name+":"+time;

        // Step 2, generate colume
        QMap<QString, QString>::ConstIterator const_i = transaction.getColum().constBegin();
        while (const_i != transaction.getColum().constEnd()) {
            line = line + ";" + const_i.key() + ":" + const_i.value();
            const_i++;
        }
        // Step 3, generate end

        line = line + ";END";
        std::cout << __FILE__ << ", addline :" << line.toStdString() << std::endl;
        v_string.append(line);

        return true;
    }


    bool isStrQEmpty() {
        return v_string.empty();
    }

    const char* getFirstString() {
        assert(!v_string.empty());
        return v_string[0].toStdString().c_str();
    }

    void removeFirst() {
        v_string.removeFirst();
    }

private:
    QVector<QString> v_string;
};

#endif // TRANSANALYSIS_H
